package utils

import (
	"fmt"
	jsoniter "github.com/json-iterator/go"
	"github.com/mitchellh/mapstructure"
	"reflect"
	"unsafe"
)

func JsonMarshal(st interface{}) ([]byte, error) {
	return jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(st)
}

func JsonUnmarshal(bt []byte, st interface{}) error {
	return jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(bt, st)
}

func StringToBytes(s string) []byte {
	return *(*[]byte)(unsafe.Pointer(
		&struct {
			string
			Cap int
		}{s, len(s)},
	))
}

func BytesToString(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}

func Struct2Struct(source interface{}, target interface{}) error {
	skd := reflect.TypeOf(source).Kind()
	if skd != reflect.Ptr {
		return fmt.Errorf("type of param st must be ptr")
	}
	tkd := reflect.TypeOf(target).Kind()
	if tkd != reflect.Ptr {
		return fmt.Errorf("type of param st must be ptr")
	}
	sct := reflect.TypeOf(source).Elem()
	scv := reflect.ValueOf(source).Elem()
	tt := reflect.TypeOf(target).Elem()
	mp := make(map[string]interface{})
	for i := 0; i < tt.NumField(); i++ {
		mp[tt.Field(i).Name] = 1
	}
	var data = make(map[string]interface{})
	for i := 0; i < sct.NumField(); i++ {
		if _, ok := mp[sct.Field(i).Name]; ok {
			data[sct.Field(i).Name] = scv.Field(i).Interface()
		}
	}
	if err := mapstructure.Decode(data, target); err != nil {
		return err
	}
	return nil
}

// St2Js2Mp todo:主要利用struct2json，omitempty移除多余字段
func St2Js2Mp(st interface{}) (map[string]interface{}, error) {
	jsonBt, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(st)
	if err != nil {
		return nil, fmt.Errorf("St2Js2Mp Error => %v\n", err.Error())
	}
	m := make(map[string]interface{})
	err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jsonBt, &m)
	if err != nil {
		return nil, fmt.Errorf("St2Js2Mp Error => %v\n", err.Error())
	}
	return m, nil
}
